package k8s

import (
	"fmt"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
)

//client 文件
type Client struct {
	//用于维护K8S 自身资源
	K8sClient K8sClientInterface

	// 用于维护K8S 自身缓存资源
	SharedInformerFactory K8sInformerInterface
}

//配置文件
type ClientOptions struct {
	// 用于维护K8S自身资源缓存
	StopChan   <-chan struct{}
	Config     *rest.Config
	k8sOptions *KubernetesOptions
}

/*func (opt *ClientOptions) SetConfig(kubeconfig, master string) {
	// 初始化config
	var config *rest.Config
	var err error

	if kubeconfig == "" {
		config, err = rest.InClusterConfig()
		if err != nil {
			fmt.Printf("初始化k8s config 失败 %v\n", err)
		}

	} else {
		config, err = clientcmd.BuildConfigFromFlags(master, kubeconfig)
		if err != nil {
			fmt.Printf("初始化k8s config 失败 %v\n", err)
		}
	}

	opt.Config = config
}

func (opt *ClientOptions) GetConfig() *rest.Config {

	var config *rest.Config

	if opt.Config != nil {
		config = opt.Config
	}
	return config
}
*/
func NewClientOptionsWithConfig(kubeconfig, master string, stopChan <-chan struct{}) *ClientOptions {
	config, err := buildConfig(kubeconfig, master)

	if err != nil {
		fmt.Printf("初始化k8s config 失败 %v\n", err)
		return nil
	}

	return &ClientOptions{
		k8sOptions: &KubernetesOptions{
			KubeConfig: config,
			QPS:        1e6,
			Burst:      1e6,
		},
		StopChan: stopChan,
		Config:   config,
	}
}

func buildConfig(kubeconfig, master string) (*rest.Config, error) {
	// 初始化config
	var config *rest.Config
	var err error

	if kubeconfig == "" {
		config, err = rest.InClusterConfig()
		if err != nil {
			return nil, err
		}
	} else {
		config, err = clientcmd.BuildConfigFromFlags(master, kubeconfig)
		if err != nil {
			return nil, err
		}
	}
	return config, nil
}

func NewClient(options *ClientOptions) (*Client, error) {

	var clusterClient Client
	var err error

	//初始化k8s client
	clusterClient.K8sClient, err = NewK8sClient(options.k8sOptions)
	if err != nil {
		fmt.Printf("初始化k8s client 失败 %v\n", err)
	}
	//

	//初始化informer client
	clusterClient.SharedInformerFactory, err = NewInformerFactory(clusterClient.K8sClient.Kubernetes(), clusterClient.K8sClient.Istio())
	if err != nil {
		fmt.Printf("初始化informer client 失败 %v\n", err)
	}

	//启动缓存
	// 获取K8S原生资源信息
	discoveryClient := clusterClient.K8sClient.Kubernetes().Discovery()
	_, apiResourcesList, err := discoveryClient.ServerGroupsAndResources()

	if err != nil {
		return nil, err
	}

	isResourceExists := func(resource schema.GroupVersionResource) bool {
		for _, apiResource := range apiResourcesList {
			if apiResource.GroupVersion == resource.GroupVersion().String() {
				for _, rsc := range apiResource.APIResources {
					if rsc.Name == resource.Resource {
						return true
					}
				}
			}
		}
		return false
	}

	k8sGVRs := []schema.GroupVersionResource{
		{Group: "", Version: "v1", Resource: "namespaces"},
		{Group: "", Version: "v1", Resource: "nodes"},
		{Group: "", Version: "v1", Resource: "resourcequotas"},
		{Group: "", Version: "v1", Resource: "pods"},
		{Group: "", Version: "v1", Resource: "services"},
		{Group: "", Version: "v1", Resource: "persistentvolumeclaims"},
		{Group: "", Version: "v1", Resource: "secrets"},
		{Group: "", Version: "v1", Resource: "configmaps"},
		{Group: "", Version: "v1", Resource: "serviceaccounts"},

		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"},
		{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"},

		{Group: "apps", Version: "v1", Resource: "deployments"},
		{Group: "apps", Version: "v1", Resource: "daemonsets"},
		{Group: "apps", Version: "v1", Resource: "replicasets"},
		{Group: "apps", Version: "v1", Resource: "statefulsets"},
		{Group: "apps", Version: "v1", Resource: "controllerrevisions"},

		{Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"},

		{Group: "batch", Version: "v1", Resource: "jobs"},
		{Group: "batch", Version: "v1beta1", Resource: "cronjobs"},

		{Group: "extensions", Version: "v1beta1", Resource: "ingresses"},

		{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"},

		{Group: "networking.k8s.io", Version: "v1", Resource: "networkpolicies"},
	}

	for _, gvr := range k8sGVRs {
		if !isResourceExists(gvr) {
			fmt.Printf("资源 %s 不存在", gvr)
		} else {
			_, err := clusterClient.SharedInformerFactory.KubernetesSharedInformerFactory().ForResource(gvr)
			if err != nil {
				fmt.Printf("创建监听器失败 %s", gvr)
				return nil, err
			}
		}
	}
	clusterClient.SharedInformerFactory.Start(options.StopChan)
	clusterClient.SharedInformerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(options.StopChan)



	return &clusterClient, nil

}
